﻿using System;
using System.Collections.Generic;

namespace TfsReports.Web.Models
{
    /// <summary>
    /// ChurnTable
    /// </summary>
    public class ChurnTable : Dictionary<DateTime, Dictionary<int, Changes>>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ChurnTable"/> class.
        /// </summary>
        /// <param name="churns">The churns.</param>
        public ChurnTable(List<Churn> churns)
        {
            List<DateTime> dates = new List<DateTime>();
            People = new List<Person>();
            churns.Sort((c1, c2) => c1.Date.CompareTo(c2.Date));
            for (DateTime d = churns[0].Date.Date; d <= churns[churns.Count - 1].Date.Date; d = d.AddDays(1))
                dates.Add(d);
            churns.ForEach(churn =>
            {
                if (People.Find(person => person.Id == churn.Person.Id) == null)
                    People.Add(churn.Person);
            });
            dates.Sort();
            Start = dates[0];
            End = dates[dates.Count - 1];
            People.Sort((p1, p2) => p1.Title.CompareTo(p2.Title));
            dates.ForEach(d =>
            {
                Add(d, new Dictionary<int, Changes>());
                People.ForEach(person => this[d].Add(person.Id, new Changes()));
            });
            Totals = new Dictionary<int, ChangeTotal>();
            People.ForEach(p => Totals.Add(p.Id, new ChangeTotal()));
            churns.ForEach(Add);
            SetTotals();
        }

        /// <summary>
        /// Sets the totals.
        /// </summary>
        private void SetTotals()
        {
            foreach (KeyValuePair<DateTime, Dictionary<int, Changes>> dateData in this)
                foreach (KeyValuePair<int, Changes> peopleData in dateData.Value)
                {
                    List<int> changesetIds = new List<int>();
                    foreach (Change change in peopleData.Value)
                    {
                        Totals[peopleData.Key].LinesAdded += change.LinesAdded;
                        Totals[peopleData.Key].LinesModified += change.LinesModified;
                        Totals[peopleData.Key].LinesDeleted += change.LinesDeleted;
                        if (!changesetIds.Contains(change.ChangesetId))
                            changesetIds.Add(change.ChangesetId);
                    }
                    Totals[peopleData.Key].Commits += changesetIds.Count;
                }
        }

        /// <summary>
        /// Adds the specified churn.
        /// </summary>
        /// <param name="churn">The churn.</param>
        private void Add(Churn churn)
        {
            this[churn.Date.Date][churn.Person.Id].Add(churn.Change);
        }

        /// <summary>
        /// Gets or sets the people.
        /// </summary>
        /// <value>The people.</value>
        public Dictionary<int, ChangeTotal> Totals { get; private set; }

        /// <summary>
        /// Gets or sets the people.
        /// </summary>
        /// <value>The people.</value>
        public List<Person> People { get; private set; }

        /// <summary>
        /// Gets or sets the start.
        /// </summary>
        /// <value>The start.</value>
        public DateTime Start { get; private set; }

        /// <summary>
        /// Gets or sets the end.
        /// </summary>
        /// <value>The end.</value>
        public DateTime End { get; private set; }
    }
}
